﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using ICSharpCode.AvalonEdit.Folding;
using ICSharpCode.AvalonEdit.CodeCompletion;

using System.IO;
using System.Windows.Threading;
using System.Xml;

using ICSharpCode.AvalonEdit.Highlighting;
using Microsoft.Win32;


namespace BDDEditor
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public ICommand SaveFileCommand { get; set; }

        private BDDLoader bddloader;

        private CompletionWindow completionWindow;

        private bool IsLastLetterWhiteSpace;

        public MainWindow()
        {
            IsLastLetterWhiteSpace = true;
            SaveFileCommand = new SaveCommand(SaveFile);
            this.DataContext = this;
            // Load our custom highlighting definition
            IHighlightingDefinition customHighlighting;
            using (Stream s = typeof(MainWindow).Assembly.GetManifestResourceStream("BDDEditor.CustomHighlighting.xshd"))
            {
                if (s == null)
                    throw new InvalidOperationException("Could not find embedded resource");
                using (XmlReader reader = new XmlTextReader(s))
                {
                    customHighlighting = ICSharpCode.AvalonEdit.Highlighting.Xshd.
                        HighlightingLoader.Load(reader, HighlightingManager.Instance);
                }
            }
            // and register it in the HighlightingManager
            HighlightingManager.Instance.RegisterHighlighting("BDD", new string[] { ".cool" }, customHighlighting);

            bddloader = new BDDLoader();
            bddloader.FeauteFolder = Settings1.Default.FeatureFolder;

            bddloader.LoadDataFromFiles();
            InitializeComponent();

            //textEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition("C#");
            textEditor.SyntaxHighlighting = customHighlighting;
            // initial highlighting now set by XAML

            textEditor.TextArea.TextEntering += textEditor_TextArea_TextEntering;
            textEditor.TextArea.TextEntered += textEditor_TextArea_TextEntered;
            textEditor.TextChanged += new EventHandler(textEditor_TextChanged);

            DispatcherTimer foldingUpdateTimer = new DispatcherTimer();
            foldingUpdateTimer.Interval = TimeSpan.FromSeconds(2);
            foldingUpdateTimer.Tick += foldingUpdateTimer_Tick;
            foldingUpdateTimer.Start();
            FeatureFolder.Text = Settings1.Default.FeatureFolder;
        }

        void textEditor_TextChanged(object sender, EventArgs e)
        {
            if (textEditor.TextArea.Caret.Offset > 1)
                IsLastLetterWhiteSpace = char.IsWhiteSpace(textEditor.Text[textEditor.TextArea.Caret.Offset - 2]);
            else
                IsLastLetterWhiteSpace = true;
        }

        string currentFileName;

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            System.Windows.Forms.FolderBrowserDialog dlg = new System.Windows.Forms.FolderBrowserDialog();
            var result = dlg.ShowDialog();
            if (result == System.Windows.Forms.DialogResult.OK)
            {
                bddloader.FeauteFolder = dlg.SelectedPath;
                FeatureFolder.Text = dlg.SelectedPath;
                bddloader.LoadDataFromFiles();
                Settings1.Default.FeatureFolder = dlg.SelectedPath;
                Settings1.Default.Save();
            }
        }

        void newFileClick(object sender, RoutedEventArgs e)
        {
            currentFileName = null;
            this.Title = "BDD Editor - New File";
        }

        void openFileClick(object sender, RoutedEventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.InitialDirectory = bddloader.FeauteFolder;
            if (currentFileName != null)
            {
                dlg.InitialDirectory = new FileInfo(currentFileName).DirectoryName;
            }
            dlg.DefaultExt = ".feature,.txt";
            dlg.CheckFileExists = true;
            if (dlg.ShowDialog() ?? false)
            {
                currentFileName = dlg.FileName;
                textEditor.Load(currentFileName);
                this.Title = "BDD Editor -" + dlg.FileName;
                //textEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinitionByExtension(Path.GetExtension(currentFileName));
            }
        }

        void saveFileClick(object sender, EventArgs e)
        {
            SaveFile(true);
        }

        private void SaveFile(bool showDialog)
        {
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.InitialDirectory = bddloader.FeauteFolder;
            if (currentFileName != null)
            {
                dlg.InitialDirectory = new FileInfo(currentFileName).DirectoryName;
                dlg.FileName = currentFileName;
            }

            if (showDialog || currentFileName == null)
            {
                
                dlg.DefaultExt = ".feature";
                dlg.Filter = "BDD files (*.feature, *.txt)|*.feature;*.txt|All files (*.*)|*.*";
                if (dlg.ShowDialog() ?? false)
                {
                    currentFileName = dlg.FileName;
                }
                else
                {
                    return;
                }

            }
            textEditor.Save(currentFileName);
            bddloader.LoadDataFromFiles();
            this.Title = "BDD Editor -" + currentFileName;
        }        

        void textEditor_TextArea_TextEntered(object sender, TextCompositionEventArgs e)
        {
            if (completionWindow == null && e.Text != "\n" && IsLastLetterWhiteSpace)
            {
                //textEditor.Text.Insert(textEditor.TextArea.Caret.Offset - 1, " ");
                // open code completion after the user has pressed dot:
                completionWindow = new CompletionWindow(textEditor.TextArea);
                //completionWindow.CloseAutomatically = true;
                // provide AvalonEdit with the data:
                IList<ICompletionData> data = completionWindow.CompletionList.CompletionData;

                foreach (var item in bddloader.completionList)
                {
                    data.Add(item);
                }

                completionWindow.Width = 400;
                completionWindow.Show();
                completionWindow.CaretPositionChanged(null, null);
                completionWindow.CloseWhenCaretAtBeginning = true;
                completionWindow.Closed += delegate
                {
                    completionWindow = null;
                };
            }
        }

        void textEditor_TextArea_TextEntering(object sender, TextCompositionEventArgs e)
        {
            if (e.Text.Length > 0 && completionWindow != null)
            {
                if (!char.IsLetterOrDigit(e.Text[0]) && e.Text != " ")
                {
                    // Whenever a non-letter is typed while the completion window is open,
                    // insert the currently selected element.
                    completionWindow.CompletionList.RequestInsertion(e);
                    IsLastLetterWhiteSpace = true;
                }
            }
            // do not set e.Handled=true - we still want to insert the character that was typed
        }

        #region Folding
        FoldingManager foldingManager;
        AbstractFoldingStrategy foldingStrategy;

        void HighlightingComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (textEditor.SyntaxHighlighting == null)
            {
                foldingStrategy = null;
            }
            else
            {
                switch (textEditor.SyntaxHighlighting.Name)
                {
                    case "XML":
                        foldingStrategy = new XmlFoldingStrategy();
                        textEditor.TextArea.IndentationStrategy = new ICSharpCode.AvalonEdit.Indentation.DefaultIndentationStrategy();
                        break;
                    case "C#":
                    case "C++":
                    case "PHP":
                    case "Java":
                        textEditor.TextArea.IndentationStrategy = new ICSharpCode.AvalonEdit.Indentation.CSharp.CSharpIndentationStrategy(textEditor.Options);
                        foldingStrategy = new BraceFoldingStrategy();
                        break;
                    default:
                        textEditor.TextArea.IndentationStrategy = new ICSharpCode.AvalonEdit.Indentation.DefaultIndentationStrategy();
                        foldingStrategy = null;
                        break;
                }
            }
            if (foldingStrategy != null)
            {
                if (foldingManager == null)
                    foldingManager = FoldingManager.Install(textEditor.TextArea);
                foldingStrategy.UpdateFoldings(foldingManager, textEditor.Document);
            }
            else
            {
                if (foldingManager != null)
                {
                    FoldingManager.Uninstall(foldingManager);
                    foldingManager = null;
                }
            }
        }

        void foldingUpdateTimer_Tick(object sender, EventArgs e)
        {
            if (foldingStrategy != null)
            {
                foldingStrategy.UpdateFoldings(foldingManager, textEditor.Document);
            }
        }
        #endregion

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (textEditor.Text != "")
            {
                var result = MessageBox.Show("do u wana save?", "Save!!", MessageBoxButton.YesNoCancel);
                if (result == MessageBoxResult.Yes)
                {
                    saveFileClick(null, new EventArgs());
                }
                else if (result == MessageBoxResult.Cancel)
                    e.Cancel = true;

            }
        }
    }
}